/* 
 * Double linked lists with a single pointer list head.
 * Mostly useful for hash tables where the two pointer list head is too
 * wastful.
 * You lose the ability to access the tail in O(1).
 */

struct hlist_head{
    struct hlist_node *first;
};

struct hlist_node {
    struct hlist_node *next;
    struct hlist_node **pprev;
};

#define	offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({			\
	const typeof(((type *)0)->member)*__mptr = (ptr);	\
		(type *)((char *)__mptr - offsetof(type, member)); })
#define	HLIST_HEAD_INIT { .first = NULL}
#define	HLIST_HEAD(name) struct hlist_head_name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
    h->next = NULL;
    h->pprev = NULL;
}

static inline int hlist_empty(const struct hlist_head *h)
{
    return !h->first;
}

static inline void __hlist_del(struct hlist_node *n)
{
    struct hlist_node *next = n->next;
    struct hlist_node **pprev = n->pprev;
    *pprev = next;
    if (next)
	next->pprev = pprev;
}

static inline void hlist_del(struct hlist_node *n)
{
    __hlist_del(n);
    n->next = LIST_POISON1;
    n->pprev = LIST_POISON2;
}

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
    struct hlist_node *first = h->first;
    n->next = first;
    if (first)
	first->pprev = &n->next;
    h->first = n;
    n->pprev = &h->first;
}

static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next)
{
    n->pprev = next->pprev;
    n->next = next;
    next->pprev = &n->next;
    *(n->pprev) = n;
}

static inline void hlist_add_after(struct hlist_node *n, struct hlist_node *next)
{
    next->next = n->next;
    n->next = next;
    next->pprev = &n->next;

    if (next->next)
	next->next->pprev = &next->next;
}

#define hlist_entry(ptr, type, member) container_of(ptr, type, member)

#define hlist_for_each(pos, head)	\
    for (pos = (head)->first; pos && ({prefetch(pos->next); 1; }); \
		pos = pos->next)

#define hlist_for_each_safe(pos, n, head)	\
    for (pos = (head)->first; pos && ({ n = pos->next; 1; });	\
	    pos = n)

#define hlist_for_each_entry(tpos, pos, head, member)		\
    for (pos = (head)->first;					\
	 pos && ({ prefetch(pos->next); 1;}) &&			\
	 	({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});\
	 pos = pos->next)

#define hlist_for_each_continue(tpos, pos, member)		\
    for (pos = (pos)->next;					\
	 pos && ({ prefetch(pos->next); 1;}) &&			\
	     	({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});\
	 pos = pos->next)

#define hlist_for_each_entry_from(tpos, pos, member)		\
    for (; pos && ({ prefetch(pos->next); 1;}) &&		\
	   	({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});\
	 pos = pos->next)

#define hlist_for_each_entry_safe(tpos, pos, n, head, member)	\
    for (pos = (head)->first;					\
	 pos && ({ n = pos->next; 1; }) &&			\
	    ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});	\
	 pos = n)


